﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace BeanboxSoftware.BeanMap
{
  namespace Internal
  {
    public abstract partial class DictionaryCommonBase<TKey, TValue>
    {
      [DataContract]
      [KnownType("GetKnownTypes")]
      protected class DictionaryCommonBaseSerialData
      {
        [DataMember]
        public IDictionary<TKey, TValue> DataStorage { get; set; }

        private static Type[] GetKnownTypes()
        {
          return new Type[] { typeof(DictionaryCommonBase<TKey, TValue>.DictionaryCommonBaseSerialData) };
        }
      }

      protected DictionaryCommonBaseSerialData _storage;

      protected virtual DictionaryCommonBaseSerialData NewStorage()
      {
        return new DictionaryCommonBaseSerialData();
      }

      // preserve _data

      protected virtual void ReadStorage()
      {
        _data = _storage.DataStorage;
      }

      protected virtual void WriteStorage()
      {
        _storage = NewStorage();
        _storage.DataStorage = RetrieveDataHandle();
      }
    }

    public abstract partial class MapBase<TGen, TValue, TPrimaryKey, TPrimaryValue> : DictionaryCommonBase<TPrimaryKey, TPrimaryValue>
    {
      [DataContract]
      [KnownType("GetKnownTypes")]
      protected class MapBaseSerialData : DictionaryCommonBaseSerialData
      {
        [DataMember]
        public KeyNotFoundBehavior KeyNotFoundBehaviorStorage { get; set; }

        [DataMember]
        public TValue DefaultValueStorage { get; set; }

        private static Type[] GetKnownTypes()
        {
          return new Type[] { typeof(MapBase<TGen, TValue, TPrimaryKey, TPrimaryValue>.MapBaseSerialData) };
        }
      }

      protected override DictionaryCommonBaseSerialData NewStorage()
      {
        return new MapBaseSerialData();
      }

      // preserve behavior
      protected override void ReadStorage()
      {
        base.ReadStorage();
        var info = (_storage as MapBaseSerialData);

        this.KeyNotFoundBehavior = info.KeyNotFoundBehaviorStorage;

        if (this.KeyNotFoundBehavior == BeanMap.KeyNotFoundBehavior.DefaultValue)
        {
          this.DefaultValue = info.DefaultValueStorage;
        }
        else if (this.KeyNotFoundBehavior == BeanMap.KeyNotFoundBehavior.DefaultGeneration)
        {
          this._faultedGeneration = true;
        }
      }

      protected override void WriteStorage()
      {
        base.WriteStorage();
        (_storage as MapBaseSerialData).KeyNotFoundBehaviorStorage = KeyNotFoundBehavior;
        (_storage as MapBaseSerialData).DefaultValueStorage = _defaultValue;
      }
    }
  }
}
